//
// Created by song on 16-11-18.
//

#ifndef C0COMPILER_PARSER_H
#define C0COMPILER_PARSER_H

#include <set>
#include <stdlib.h>
#include "ASTNode.h"
#include "Lexer.h"
#include "../helper/Log.h"

class Parser{
private:
    map<TokenType,string> typeStr;
    set<TokenType> statementFirstSet;
    set<TokenType> factorFirstSet;
    set<TokenType> relationOperatorSet;
    vector<Token *> tokens;
    int currentIndex;
    TokenType cur;
    Lexer lexer;
    int skipCount;//do not jump too many times.
    bool supportElse;
public:
    ASTNode * ast;
    Parser(Lexer& lexer) {
        this->tokens = lexer.getTokenList();
        this->lexer = lexer;
        this->supportElse = true;
        currentIndex = 0;
        skipCount=0;
        cur = tokens[0]->type;
        statementFirstSet.insert(If);
        statementFirstSet.insert(While);
        statementFirstSet.insert(Switch);
        statementFirstSet.insert(Id);
        statementFirstSet.insert(LeftB);
        statementFirstSet.insert(Semicolon);
        statementFirstSet.insert(Return);
        statementFirstSet.insert(Scanf);
        statementFirstSet.insert(Printf);
        factorFirstSet.insert(Id);
        factorFirstSet.insert(LeftR);
        factorFirstSet.insert(Add);
        factorFirstSet.insert(Minus);
        factorFirstSet.insert(Num);
        factorFirstSet.insert(CharLiteral);
        relationOperatorSet = {LessEqual, LessThan, GreatEqual, GreatThan, NotEqual, Equal};
        typeStr[Id]=          "IDENTIFIER";
//        typeStr[SystemFun]=   "SYSTEM_FUNCTION";
        typeStr[Scanf]=       "scanf";
        typeStr[Printf]=      "prinf";
        typeStr[Num]=         "NUMBER";
//        typeStr[Type]=        "TYPE";
        typeStr[CommonType]=  "COMMON_TYPE";
        typeStr[Int]=         "int";
        typeStr[Char]=        "char";
        typeStr[Void]=        "void";
//        typeStr[Operator]=    "OPERATOR";
//        typeStr[AlgebraicOp]= "OP.ALGEBRAIC";
//        typeStr[AddSubOp]=    "OP.ADD_OR_SUB";
        typeStr[Add]=         "+";
        typeStr[Minus]=       "-";
//        typeStr[MultiDivOp]=  "OP.MUL_OR_DIV";
        typeStr[Mul]=         "*";
        typeStr[Div]=         "/";
//        typeStr[RelationOp]=  "OP.RELATIONAL";
        typeStr[LessThan]=    "<";
        typeStr[LessEqual]=   "<=";
        typeStr[GreatThan]=   ">";
        typeStr[GreatEqual]=  ">=";
        typeStr[NotEqual]=    "!=";
        typeStr[Equal]=       "==";
//        typeStr[Qualifier]=   "QUALIFIER";
        typeStr[LeftR]=       "(";
        typeStr[RightR]=      ")";
        typeStr[LeftB]=       "{";
        typeStr[RightB]=      "}";
        typeStr[LeftS]=       "[";
        typeStr[RightS]=      "]";
        typeStr[Comma]=       ",";
        typeStr[Semicolon]=   ";";
        typeStr[Colon]=       ":";
        typeStr[Assign]=      "=";
//        typeStr[Keyword]=     "KEYWORD";
        typeStr[If]=          "if";
        typeStr[While]=       "while";
        typeStr[Default]=     "default";
        typeStr[Case]=        "case";
        typeStr[Return]=      "return";
        typeStr[Switch]=      "switch";
        typeStr[Const]=       "const";
        typeStr[CharLiteral]= "CHAR_LITERAL";
        typeStr[StringLiteral]="STRING_LITERAL";
    }

    ASTNode* parse(){
        sourceCodeFile();
        return ast;
    }

    void printAST(){
        printAST(ast, 0);
    }

private:
    void printAST(ASTNode* root, int level){
        for(int i=0;i<level;i++){
            cout<<"|---";
        }
        cout<<root->toString()<<endl;
        if(!root->isLeaf()){
            vector<ASTNode*>::const_iterator iter;
            for(iter = root->children.begin();
                iter!= root->children.end(); iter++){
                printAST(*iter, level+1);
            }
        }
    }


    void printTokens(int from, int to){
        if(from<0) from=0;
        if(to>=tokens.size())to= (int) (tokens.size() - 1);
        for(int i=from;i<=to;i++){
            cout<<tokens[i]->content<<" ";
        }
        cout<<endl;
    }

    bool in(TokenType cur, set<TokenType> set1){
        return (set1.count(cur)>0);
    }

    void jump2NextLine(){
        int curIndex = tokens[currentIndex]->sourceIndex;
        int nextLineBreakIndex = lexer.nextLineBreakPos(curIndex);
        do{
            next();
            curIndex = tokens[currentIndex]->sourceIndex;
        }while(curIndex > nextLineBreakIndex);
    }

    void next(){
        currentIndex++;
        cur = (tokens[currentIndex])->type;
    }

    string getCurStr(){
        return (tokens[currentIndex])->content;
    }

    int getCurInt(){
        return atoi(getCurStr().c_str());
    }

    //when call this method, you must keep currentIndex+i<tokens.size()
    //which can be checked by
    TokenType ahead(int i){
        return (tokens[currentIndex+i])->type;
    }

    // this count exclude current token.
    int remain(){
        return (int) (tokens.size() - currentIndex - 1);
    }


    int sourcePos() {
        return tokens[currentIndex]->sourceIndex;
    }

    int lastSourceEndPos() {
        Token* t = tokens[currentIndex-1];
        return t->sourceIndex + t->length;
    }

    void skipUntil(Error::SyntaxError* err, set<TokenType> l){
        if(skipCount>4){
            syntaxErr(Error::Too_Many_Errors);
        }
        string lastErrMsg = Error::errorList[Error::errorList.size()-1]->what();
        if(lastErrMsg==err->what()){
            if(skipCount>2){
                jump2NextLine();
            }else{
                next();
            }
        }else{
            while(l.count(cur)==0 && remain()>0){
                next();
            }
        }
        skipCount++;
//        set<TokenType>::const_iterator iter;
//        for(iter=l.begin();iter!=l.end();iter++){
//            cerr<< typeStr[(*iter)] <<endl;
//        }
    }

    void syntaxErr(Error::ErrorNo no){
        Error::nextErrorDetail <<"current: "<<tokens[currentIndex]->content<<endl;
        Error::nextErrorDetail << lexer.charIndex2pos(tokens[currentIndex]->sourceIndex)<<endl;
        Error::nextErrorDetail << lexer.pointPos(tokens[currentIndex]->sourceIndex)<<endl;
        Error::syntax(tokens[currentIndex]->sourceIndex, no);
    }

    void sourceCodeFile () {
        ast = new ASTNode(SourceCode);

        set<TokenType> skipUntilSet = {Const, Int, Char, Void};
        while(cur==Const) {
            try{
                constDeclaration(ast, skipUntilSet);
            }catch(Error::SyntaxError* err){
                skipUntil(err,{Semicolon});
                skipUntil(err,skipUntilSet);
            }
        }

        skipUntilSet = {Int, Char, Void};
        while(cur==Int || cur==Char){
            if(remain()>=2){
                if(ahead(2)!=LeftR) {
                    try{
                        variableDeclaration(ast, skipUntilSet);
                    }catch (Error::SyntaxError* err){
                        skipUntil(err,{Semicolon});
                        skipUntil(err,skipUntilSet);
                    }
                }else{
                    break;
                }
            }else{
                syntaxErr(Error::Expect_Void_Main);
            }
        }

        while(cur==Int || cur==Char || cur==Void){
            if(remain()>=2) {
                if (ahead(2) == LeftR) {
                    if ((cur == Void) && (tokens[currentIndex + 1]->content == "main")) {
                        break;
                    } else {
                        try{
                            ast->addChild(functionDeclaration(skipUntilSet));
                        }catch(Error::SyntaxError* err){
                            skipUntil(err,{RightB});
                            skipUntil(err,skipUntilSet);
                        }
                    }
                } else {
                    syntaxErr(Error::Expect_LeftR);
                }
            }else{
                syntaxErr(Error::Expect_Void_Main);
            }
        }

        if(cur==Void){
            if(tokens[currentIndex + 1]->content == "main"){
                ast->addChild(functionDeclaration({EndOfFile}));
            }else{
                Error::nextErrorDetail<< "Just found void main but now we lost it. at " <<__FILE__ << __LINE__;
                Error::internal(Error::Should_Not_Happen);
            }
        }else{
            syntaxErr(Error::Expect_Void_Main);
        }

        if(cur==EndOfFile){
//            Log::trace("Program Parse Complete.");
        }else{
            Error::nextErrorDetail<< "Do not found a valid EOF. at " <<__FILE__ << __FUNCTION__ << __LINE__;
            Error::internal(Error::Should_Not_Happen);
        }
    }


    void constDeclaration(ASTNode *parent, set<TokenType> skipUntilSet) {
        next(); // const already be matched.
        TokenType type = cur;
        if(type==Int){
            do{
                next();//step over int or char or ,
                int start = sourcePos();
                if(cur==Id){
                    string id = getCurStr();
                    next();
                    if(cur==Assign){
                        next();
                        int value = integer(true);
                        ASTNode* me = new ASTNode(ConstDeclar);
                        me->value = value;
                        me->content = id;
                        me->contentType = type;
                        me->start = start;
                        me->end = lastSourceEndPos();
                        parent->addChild(me);
                    }else{
                        syntaxErr(Error::Expect_Assign);
                    }
                }else{
                    syntaxErr(Error::Expect_Identifier);
                }
            }while(cur==Comma);
        }else if(type==Char){
            do{
                next();
                int start = sourcePos();
                if(cur==Id){
                    string name = getCurStr();
                    next();
                    if(cur==Assign){
                        next();
                        if(cur==CharLiteral){
                            string content = getCurStr();
                            next();
                            ASTNode* me = new ASTNode(ConstDeclar);
                            me->ch = content[1];
                            me->content = name;
                            me->contentType = type;
                            me->start = start;
                            me->end = lastSourceEndPos();
                            parent->addChild(me);

                        }else{
                            syntaxErr(Error::Expect_CharLiteral);
                        }
                    }else{
                        syntaxErr(Error::Expect_Assign);
                    }
                }else{
                    syntaxErr(Error::Expect_Identifier);
                }
            }while(cur==Comma);
        }else{
            syntaxErr(Error::Expect_Char_Int);
        }

        if(cur!=Semicolon){
            syntaxErr(Error::Expect_Semicolon);
        }else{
            next();
        }
    }

    void variableDeclaration(ASTNode *parent, set<TokenType> skipUntilSet) {
        TokenType type = cur;
        do {
            try{
                next();
                int start = sourcePos();
                if (cur == Id) {
                    string idName = getCurStr();
                    next();
                    if (cur == LeftS) {//"["
                        next();
                        int arraySize = integer(false);
                        if (cur == RightS) {//"]"
                            next();
                            ASTNode* me = new ASTNode(ArrayDeclar);
                            me->content = idName;
                            me->contentType = type;
                            me->value = arraySize;
                            me->start = start;
                            me->end = lastSourceEndPos();
                            parent->addChild(me);
                        } else {
                            syntaxErr(Error::Expect_RightS);
                        }
                    }else{
                        ASTNode* me = new ASTNode(VariableDeclar);
                        me->content = idName;
                        me->contentType = type;
                        me->start = start;
                        me->end = lastSourceEndPos();
                        parent->addChild(me);
                    }
                } else {
                    syntaxErr(Error::Expect_Identifier);
                }
            }catch(Error::SyntaxError* err){
                skipUntil(err,Utils::mergeSet(skipUntilSet,{Comma,Semicolon}));
            }
        }while(cur==Comma);


        if(cur!=Semicolon){
            syntaxErr(Error::Expect_Semicolon);
        }else{
            next();
        }
    }

    int integer(bool allowSign){
        int sign=1;
        bool hasSign = false;

        if(cur==Add || cur==Minus){
            if(allowSign){
                if(cur==Minus) {
                    sign=-1;
                }else{ //cur==Add
                    sign=1;
                }
                hasSign = true;
                next();
            }else{
                syntaxErr(Error::Expect_Number);//throw SyntaxError("expect unsigned number but found +/-");
            }
        }
        int value=0;
        if(cur==Num){
            value = getCurInt();
            if(value==0){
                if(hasSign) {
                    Error::warn("should not add +/- before 0");
                }
                if(!allowSign){
                    Error::semantic(Error::Array_Size_Must_Larger_Than_Zero);//("expect number > 0");
                }
            }
            value *= sign;
            next();
        }else{
            syntaxErr(Error::Expect_Number);
        }
        return value;
    }

    ASTNode *functionDeclaration(set<TokenType> skipUntilSet) {
        ASTNode* me = new ASTNode(FunctionDeclar);
        // type of function return value, must guarantee that this is checked. can only be int char void.
        me->contentType = cur;
        next();
        me->start = sourcePos();
        if(cur==Id){
            me->content = getCurStr();
            next();
            me->end = lastSourceEndPos();
            if(cur==LeftR) {//"("
                next();
                if (cur != RightR) {//")" no param.
                    paramList(me);
                    if(cur!=RightR){
                        syntaxErr(Error::Expect_RightR);
                    }
                }
                next();

                if(cur==LeftB){
                    next();
                    functionBody(me, skipUntilSet);
                    if(cur==RightB){
//                        trace("function decl matched.");
                        next();
                    }else{
                        syntaxErr(Error::Expect_RightB);
                    }
                }else{
                    syntaxErr(Error::Expect_LeftB);
                }
            }else{
                syntaxErr(Error::Expect_LeftR);
            }
        }else{
            syntaxErr(Error::Expect_Identifier);
        }
        return me;
    }

    void paramList(ASTNode* parent) { //match a non-empty param list.
        int paramNum = 0;
        while(1){
            TokenType type;
            if(cur==Int || cur==Char){
                type = cur;
                int start = sourcePos();
                next();
                string idName;
                if (cur == Id) {
                    idName = getCurStr();
                    next();
                } else {
                    syntaxErr(Error::Expect_Identifier);
                }

                ASTNode* me = new ASTNode(Param);
                me->contentType = type;
                me->content = idName;
                me->start = start;
                me->end = lastSourceEndPos();
                parent->addChild(me);
                paramNum++;

                if(cur==Comma){
                    next();
                }else{
                    break;
                }
            }else{
                syntaxErr(Error::Expect_Char_Int);
            }
        }
        parent->value = paramNum;
    }


    void functionBody(ASTNode *parent, set<TokenType> skipUntilSet) {
        set<TokenType> sUs = Utils::mergeSet(skipUntilSet, statementFirstSet);

        while(cur==Const) {
            try{
                constDeclaration(parent, sUs);
            }catch (Error::SyntaxError* err){
                skipUntil(err, sUs);
            }
        }

        while(cur==Int || cur==Char){
            try{
                variableDeclaration(parent, sUs);
            }catch (Error::SyntaxError* err){
                skipUntil(err, sUs);
            }
        }

        while(in(cur,statementFirstSet)){
            try{
                statement(parent, skipUntilSet);
            }catch (Error::SyntaxError* err){
                skipUntil(err, sUs);
            }
        }
    }

    void statement(ASTNode *parent, set<TokenType> skipUntilSet) {
        set<TokenType> skipUS = Utils::mergeSet(skipUntilSet,{RightB});
        ASTNode* block;
        switch(cur){
            case If:
                parent->addChild(ifStmt(skipUntilSet));
                break;
            case While:
                parent->addChild(whileStmt(skipUntilSet));
                break;
            case Switch:
                parent->addChild(switchStmt(skipUntilSet));
                break;
            case LeftB:
                next();
                block = new ASTNode(Block);
                while(in(cur,statementFirstSet)){
                    try{
                        statement(block, skipUS);
                    }catch (Error::SyntaxError* err){
                        skipUntil(err, skipUS);
                    }
                }
                if(cur==RightB){
                    next();
                    parent->addChild(block);
                }else{
                    syntaxErr(Error::Expect_RightB);
                }
                break;
            case Id:
                if(remain()>=1){
                    if(ahead(1)==Assign || ahead(1)==LeftS) {
                        parent->addChild(assignStmt());
                    }else if(ahead(1)==LeftR){
                        parent->addChild(functionCall());
                        if(cur==Semicolon){
                            next();
                        }else{
                            syntaxErr(Error::Expect_Semicolon);
                        }
                    }else{
                        syntaxErr(Error::Invalid_Stmt_Expect_Assign_FunCall);
                    }
                }else{
                    syntaxErr(Error::Invalid_Stmt_Expect_Assign_FunCall);
                }
                break;
            case Semicolon:
                next();
//                trace("empty statement");
                break;
            case Return:
                parent->addChild(returnStmt());
                break;
            case Printf:
                parent->addChild(writeStmt());
                break;
            case Scanf:
                parent->addChild(readStmt());
                break;
            default:
                syntaxErr(Error::Expect_Stmt);
        }
    }

    ASTNode *ifStmt(set<TokenType> skipUntilSet) {
        next();
        ASTNode* me = new ASTNode(IfStmt);
        if(cur==LeftR){
            next();
            me->addChild(condition());
            if(cur==RightR){
                next();
                statement(me, skipUntilSet);
                if(supportElse){
                    if(cur==Else){
                        next();
                        statement(me, skipUntilSet);
                    }
                }
            }else{
                syntaxErr(Error::Expect_RightR);
            }
        }else{
            syntaxErr(Error::Expect_LeftR);
        }
        return me;
    }

    ASTNode *whileStmt(set<TokenType> skipUntilSet) {
        next();
        ASTNode* me = new ASTNode(WhileStmt);
        if(cur==LeftR){
            next();
            me->addChild(condition());
            if(cur==RightR){
                next();
                statement(me, skipUntilSet);
            }else{
                syntaxErr(Error::Expect_RightR);
            }
        }else{
            syntaxErr(Error::Expect_LeftR);
        }
        return me;
    }

    ASTNode *switchStmt(set<TokenType> skipUntilSet) {
        ASTNode* me = new ASTNode(SwitchStmt);
        next();//skip switch
        if(cur==LeftR){
            next();
            ASTNode* expr = expression();
            ASTNode* condition = new ASTNode(ConditionExpr);
            condition->addChild(expr);
            me->addChild(condition);
            if(cur==RightR){
                next();
                if(cur==LeftB){
                    next();
                    me->addChild(caseStmt(skipUntilSet));
                    while(cur==Case){
                        try{
                            me->addChild(caseStmt(skipUntilSet));
                        }catch(Error::SyntaxError* err){
                            skipUntil(err, Utils::mergeSet(skipUntilSet,{Case,Default}));
                        }
                    }

                    if(cur==Default){
                        next();
                        if(cur==Colon){
                            next();
                            ASTNode* defaultSeg = new ASTNode(DefaultSegment);
                            statement(defaultSeg, skipUntilSet);
                            me->addChild(defaultSeg);
                        }else{
                            syntaxErr(Error::Expect_Colon);
                        }
                    }
                    if(cur==RightB){
                        next();
                    }else{
                        syntaxErr(Error::Expect_RightB);
                    }
                }else{
                    syntaxErr(Error::Expect_LeftB);
                }
            }else{
                syntaxErr(Error::Expect_RightR);
            }
        }else{
            syntaxErr(Error::Expect_LeftR);
        }
        return me;
    }

    ASTNode *caseStmt(set<TokenType> skipUntilSet) {
        if(cur!=Case){
            syntaxErr(Error::Expect_Case);
        }
        ASTNode* me = new ASTNode(CaseSegment);
        next();
        me->start = sourcePos();
        if(cur==CharLiteral){
            me->contentType = Char;
            me->ch = getCurStr()[1];
            next();
        }else{
            me->contentType = Int;
            me->value = integer(true);
        }
        me->end = lastSourceEndPos();
        if(cur==Colon){
            next();
        }
        statement(me, skipUntilSet);
        return me;
    }

    ASTNode * condition(){
        ASTNode* me,*left, *r;
        r = new ASTNode(ConditionExpr);
        left = expression();
        if(in(cur,relationOperatorSet)){
            me = new ASTNode(RelationExpr);
            me->contentType = cur;
            me->addChild(left);
            next();
            me->addChild(expression());
            r->addChild(me);
        }else{
            r->addChild(left);
        }
        return r;
    }

    ASTNode * expression(){
        ASTNode* me;// = new ASTNode(AddSubExpr);
        vector<TokenType> opStack;//operator stack.
        vector<ASTNode*> operandStack;

        if(cur==Add || cur==Minus){
            TokenType sign;
            sign = cur;
            if(sign==Add){
                // do nothing.
            }else{
                ASTNode* zero = new ASTNode(Number);
                zero->value = 0;
                operandStack.push_back(zero);
                opStack.push_back(sign);
            }
            next();
        }
        operandStack.push_back(term());
        while(cur==Add || cur==Minus)
        {
            opStack.push_back(cur);
            next();
            operandStack.push_back(term());
        }
        for(int i=0,j=0; i<opStack.size(); i++,j++){
            me = new ASTNode(AddSubExpr);
            me->contentType = opStack[i];
            me->addChild(operandStack[j]);
            me->addChild(operandStack[j+1]);
            operandStack[j+1] = me;
        }
        return operandStack.back();
    }

    ASTNode * term(){
        ASTNode* me;
        vector<TokenType> opStack;//operator stack.
        vector<ASTNode*> operandStack;

        operandStack.push_back(factor());
        while(cur==Div || cur==Mul){
            opStack.push_back(cur);
            next();
            operandStack.push_back(factor());
        }

        for(int i=0,j=0; i<opStack.size(); i++,j++){
            me = new ASTNode(MultiDivExpr);
            me->contentType = opStack[i];
            me->addChild(operandStack[j]);
            me->addChild(operandStack[j+1]);
            operandStack[j+1] = me;
        }
        return operandStack.back();
    }

    ASTNode* arraySubscript()
    {
        ASTNode* me = new ASTNode(ArraySubscript);
        me->content = getCurStr();
        me->start = sourcePos();
        next();
        if(cur==LeftS) {
            next();
            me->addChild(expression());
            if (cur == RightS) {
//                trace("array access/subscript");
                next();
            } else {
                syntaxErr(Error::Expect_RightS);
            }
        }else{
            syntaxErr(Error::Expect_LeftS);
        }
        me->end = lastSourceEndPos();
        return me;
    }

    ASTNode * factor(){
        ASTNode* me;
        switch(cur){
            case Id:
                if(remain()>=1){
                    if(ahead(1)==LeftR){
                        return functionCall();
                    }else if(ahead(1)==LeftS){
                        return arraySubscript();
                    }else{
                        me = new ASTNode(Identifier);
                        me->content = getCurStr();
                        me->start = sourcePos();
                        next();
                        me->end = lastSourceEndPos();
                    }
                }else{
                    me = new ASTNode(Identifier);
                    me->content = getCurStr();
                    me->start = sourcePos();
                    next();
                    me->end = lastSourceEndPos();
                }
                break;
            case LeftR:
                next();
                me = expression();
                if(cur==RightR){
//                    trace("parenthesis expr");
                    next();
                }else{
                    syntaxErr(Error::Expect_RightR);
                }
                break;
            case Add:
            case Minus:
            case Num:
                me = new ASTNode(Number);
                me->start = sourcePos();
                me->value = integer(true);
                me->end = sourcePos();
                break;
            case CharLiteral:
                me = new ASTNode(CharConst);
                me->ch = getCurStr()[1];
                me->start = sourcePos();
                next();
                me->end = lastSourceEndPos();
                break;
            default:
                syntaxErr(Error::Expect_Factor_Expr);
        }
        return me;
    }

    ASTNode * functionCall(){
        ASTNode* me = new ASTNode(FunctionInvoke);
        me->content = getCurStr();
        me->contentType = cur;
        me->start = sourcePos();
        next();//id matched.
        next();// ( matched.
        if(cur!=RightR){ // has param
            while(1){
                me->addChild(expression());
                if(cur==Comma){
                    next();
                }else{
                    break;
                }
            }
        }
        if(cur==RightR){
            next();
//            trace("function call");
        }else{
            syntaxErr(Error::Expect_RightR);
        }
        me->end = lastSourceEndPos();
        return me;
    }

    ASTNode * readStmt(){
        ASTNode* me = new ASTNode(FunctionInvoke);
        me->content = getCurStr();
        me->contentType = cur;
        next();//id matched.
        if(cur==LeftR){// ( matched.
            next();
            if(cur==Id){
                ASTNode* id = new ASTNode(Identifier);
                id->content = getCurStr();
                id->start = sourcePos();
                next();
                id->end = lastSourceEndPos();
                me->addChild(id);
            }else{
                syntaxErr(Error::Expect_Identifier);
            }
            while(cur==Comma){
                next();
                if(cur==Id){
                    ASTNode* id = new ASTNode(Identifier);
                    id->content = getCurStr();
                    id->start = sourcePos();
                    next();
                    id->end = lastSourceEndPos();
                    me->addChild(id);
                }else{
                    syntaxErr(Error::Expect_Identifier);
                }
            }
            if(cur==RightR){
                next();
                if(cur==Semicolon){
                    next();
//                    trace("readStmt");
                }else{
                    syntaxErr(Error::Expect_Semicolon);
                }
            }else{
                syntaxErr(Error::Expect_RightR);
            }
        }else{
            syntaxErr(Error::Expect_LeftR);
        }
        return me;
    }

    ASTNode * writeStmt(){
        ASTNode* me = new ASTNode(FunctionInvoke);
        me->content = getCurStr();
        me->contentType = cur;
        next();//id matched.
        if(cur==LeftR) {// ( matched.
            next();
            if (cur == StringLiteral) {
//                trace("str");
                ASTNode* str = new ASTNode(StringConst);
                str->content = getCurStr();
                me->addChild(str);
                next();
                if (cur == Comma) {
                    next();
                    me->addChild(expression());
                }
            } else {
                me->addChild(expression());
            }
            if (cur == RightR) {
                next();
                if(cur==Semicolon){
                    next();
                }else{
                    syntaxErr(Error::Expect_Semicolon);
                }
            } else {
                syntaxErr(Error::Expect_RightR);
            }
        }else{
            syntaxErr(Error::Expect_LeftR);
        }
        return me;
    }

    ASTNode * assignStmt(){
        ASTNode* me = new ASTNode(AssignStmt);
        me->start = sourcePos();
        if(ahead(1)==LeftS){
            me->addChild(arraySubscript());
        }else{
            ASTNode* id = new ASTNode(Identifier);
            id->content = getCurStr();
            id->start = sourcePos();
            next();
            id->end = lastSourceEndPos();
            me->addChild(id);
        }
        if(cur==Assign){
            next();
            me->addChild(expression());
        }else{
            syntaxErr(Error::Expect_Assign);
        }
        if(cur==Semicolon){
            next();
            me->end = lastSourceEndPos();
        }else{
            syntaxErr(Error::Expect_Semicolon);
        }
//        trace("assign");
        return me;
    }

    ASTNode * returnStmt(){
        ASTNode* me = new ASTNode(ReturnStmt);
        me->start = sourcePos();
        next();//skip return;
        if(cur==LeftR){
            next();
            me->addChild(expression());
            if(cur==RightR){
                next();
            }else{
                syntaxErr(Error::Expect_RightR);
            }
        }
        if(cur==Semicolon){
            next();
            me->end = lastSourceEndPos();
        }else{
            syntaxErr(Error::Expect_Semicolon);
        }
        return me;
    }

};


#endif //C0COMPILER_PARSER_H
